﻿#include "CameraIk.h"
#ifdef _WIN32
#include <Windows.h>
#else
#include <unistd.h>
#endif
#include <QTimer>
#include <QMutexLocker>
#include <QDebug>
#include "logger.h"

#pragma execution_character_set("utf-8")

void __stdcall CameraIk::imageCallBackEx(uint32_t eventType, void *pContext){
    auto pCamera = static_cast<CameraIk*>(pContext);
    if(pCamera==nullptr)
        return;
    if(!pCamera->getReceiveStatus())
        return;
    ITKSTATUS nRet = ITKSTATUS_OK;
    unsigned bufferStatus = 0;
    ITKBUFFER hBuffer = pCamera->m_buffer;
    nRet = ItkBufferGetPrm(hBuffer, ITKBUFFER_PRM_STATE, &bufferStatus);
    if (ITKSTATUS_OK != nRet){
        printf("ITKBUFFER_PRM_STATE fail! nRet [0x%x]\n", nRet);
    }
    if (bufferStatus == ITKBUFFER_VAL_STATE_FULL || bufferStatus == ITKBUFFER_VAL_STATE_UNCOMPLETED)
    {
        int64_t nImageSize = 0;
        nRet = ItkBufferGetPrm(hBuffer, ITKBUFFER_PRM_SIZE, &nImageSize);
        if (ITKSTATUS_OK != nRet){
            printf("ItkBufferGetPrm fail! nRet [0x%x]\n", nRet);
        }

        nRet = ItkBufferRead(hBuffer, 0, pCamera->m_bufferData, (uint32_t)nImageSize);
        if (ITKSTATUS_OK != nRet){
            printf("ItkBufferRead fail! nRet [0x%x]\n", nRet);
        }

        ImageInfo imgInfo = {0};
        imgInfo.pData = pCamera->m_bufferData;
        imgInfo.nDataLen = nImageSize;
        pCamera->preProcessImage(imgInfo);
    }
}

void _stdcall CameraIk::removeCallback(void *context, ITKEVENTINFO eventInfo)
{
    auto pCamera = static_cast<CameraBase*>(context);
    if(pCamera==nullptr)
        return;
    uint32_t type = 0;
    uint64_t countstamp = 0;

    ITKSTATUS nRet = ItkEventInfoGetPrm(eventInfo, ITKEVENTINFO_PRM_TYPE, &type);
    if (ITKSTATUS_OK != nRet){
        printf("ITKEVENTINFO_PRM_TYPE fail! nRet [0x%x]\n", nRet);
    }

    nRet = ItkEventInfoGetPrm(eventInfo, ITKEVENTINFO_PRM_HOST_TIME_STAMP, &countstamp);
    if (ITKSTATUS_OK != nRet){
        printf("ITKEVENTINFO_PRM_HOST_TIME_STAMP fail! nRet [0x%x]\n", nRet);
    }
    pCamera->setStatus(CS_Unavailable);
    emit pCamera->sigErrorOccured(pCamera->getName(), CEC_Remove);
}

void CameraIk::saveParamToUserSet()
{
    //save params to user set
    setValueEnumByStr("UserSetSelector", "User1");
    setCommand("UserSetSave");
}

CameraIk::CameraIk(): CameraBase()
{
    connect(this,&CameraBase::sigErrorOccured,this,[&](const QString &name, CameraErrorCode errCode){
        if(errCode == CEC_Remove){
            reStart();
        }
    });
}

CameraIk::~CameraIk()
{

}

void CameraIk::initialize()
{
    ItkManInitialize();
    QMutexLocker mutexLocker(&mLock);
    setStatus(CS_Unavailable);
    // Enum device
    ITKSTATUS nRet = ITKSTATUS_OK;
    uint32_t numCameras = 0;
    nRet = ItkManGetDeviceCount(&numCameras);
    if (ITKSTATUS_OK != nRet){
        printf("ItkManGetDeviceCount fail! nRet [0x%x]\n", nRet);
        return ;
    }

    for (unsigned int i = 0; i < numCameras; i++){
        ITKDEV_INFO pDeviceInfo;
        nRet = ItkManGetDeviceInfo(i, &pDeviceInfo);
        if (ITKSTATUS_OK != nRet){
            printf("ItkManGetDeviceInfo fail! nRet [0x%x]\n", nRet);
            return ;
        }
        QString cameraName = QString(reinterpret_cast<char*>(pDeviceInfo.UserDefinedName));
        if(cameraName == mCamConfig.name){
            mIndex = i;
            break;
        }
    }
    if (mIndex == -1){
        LOG(WARNING) << mCamConfig.name.toStdString() << " unavailable.";
        return ;
    }
    setStatus(CS_Closed);
}

void CameraIk::openCamera()
{
    if(mStatus != CS_Closed)
        return;
    // Open device
    auto nRet = ItkDevOpen(mIndex, ITKDEV_VAL_ACCESS_MODE_EXCLUSIVE, &m_handle);
    if (ITKSTATUS_OK != nRet){
        printf("Open Device fail! nRet [0x%x]\n", nRet);
        return;
    }
    createStreamAndBuffer();
    configureStream();
    setStatus(CS_Opened);
    // printf("Open Device succeed! nRet [0x%x]\n", nRet);
}

void CameraIk::startGrabbing()
{
    if(mStatus == CS_Opened){
        int nRet;
        // Start grab image
        nRet = ItkStreamStart(m_hStream, ITKSTREAM_CONTINUOUS);;
        if (ITKSTATUS_OK != nRet){
            //            printf("Start Grabbing fail! nRet [0x%x]\n", nRet);
            LOG(WARNING) << mCamConfig.name.toStdString() << " ItkStreamStart fail! nRet:" << QByteArray::number(nRet,16).toStdString();
            return;
        }
        setStatus(CS_Grabbing);
    }
}

void CameraIk::stopGrabbing()
{
    // Stop grab image
    if(mStatus == CS_Grabbing){
        auto nRet = ItkStreamStop(m_hStream);
        if (ITKSTATUS_OK != nRet){
            //            printf("Stop Grabbing fail! nRet [0x%x]\n", nRet);
            LOG(WARNING) << mCamConfig.name.toStdString() << " ItkStreamStop fail! nRet:" << QByteArray::number(nRet,16).toStdString();
            return;
        }
        setStatus(CS_Opened);
    }
}

void CameraIk::closeCamera()
{
    if(mStatus == CS_Opened){
        setStatus(CS_Closing);
        // Close device
        auto nRet = ItkDevClose(m_handle);
        if (ITKSTATUS_OK != nRet){
            //            printf("Close Device fail! nRet [0x%x]\n", nRet);
            LOG(WARNING) << mCamConfig.name.toStdString() << " MV_CC_CloseDevice fail! nRet:" << QByteArray::number(nRet,16).toStdString();
            return;
        }
        setStatus(CS_Closed);
    }
}

void CameraIk::releaseCamera()
{
    // Destroy handle
    if(m_handle){
        auto nRet = ItkManTerminate();;
        if (ITKSTATUS_OK != nRet){
            // printf("Destroy Handle fail! nRet [0x%x]\n", nRet);
            LOG(WARNING) << mCamConfig.name.toStdString() << " ItkManTerminate fail! nRet:" << QByteArray::number(nRet,16).toStdString();
        }
    }
    m_handle = nullptr;
    setStatus(CS_Unavailable);
}

void CameraIk::preProcessImage(const ImageInfo &imgInfo)
{
    if(imgInfo.pData == nullptr || mStatus != CS_Grabbing){
        return;
    }
    int enDstPixelType = getPixelFormat();
    QImage::Format imgFormat;
    int nChannelNum;
    if (isColor(enDstPixelType)){
        imgFormat = QImage::Format_RGB888;
        nChannelNum = 3;
    } else {
        imgFormat = QImage::Format_Indexed8;
        nChannelNum = 1;
    }
    IntValue width = getValueInt64("Width");
    IntValue height = getValueInt64("Height");
    QImage image(imgInfo.pData, width.val, height.val, width.val * nChannelNum, imgFormat);
    emit sigImage(mCamConfig.name, image);
}

QStringList CameraIk::enumCameraList()
{
    uint32_t numCameras = 0;
    auto nRet = ItkManGetDeviceCount(&numCameras);
    if (ITKSTATUS_OK != nRet){
        printf("ItkManGetDeviceCount fail! nRet [0x%x]\n", nRet);
        return QStringList();
    }
    QStringList nameList;
    for (unsigned int i = 0; i < numCameras; i++){
        ITKDEV_INFO pDeviceInfo;
        nRet = ItkManGetDeviceInfo(i, &pDeviceInfo);
        if (ITKSTATUS_OK != nRet){
            printf("ItkManGetDeviceInfo fail! nRet [0x%x]\n", nRet);
            continue;
        }
        QString cameraName = QString(reinterpret_cast<char*>(pDeviceInfo.UserDefinedName));
        nameList << cameraName;
    }
    return nameList;
}

bool CameraIk::isColor(int pixelFormat)
{
    switch(pixelFormat){
    case ITKBUFFER_VAL_FORMAT_BAYER_GR8:
    case ITKBUFFER_VAL_FORMAT_BAYER_RG8:
    case ITKBUFFER_VAL_FORMAT_BAYER_GB8:
    case ITKBUFFER_VAL_FORMAT_BAYER_BG8:
        return true;
    case ITKBUFFER_VAL_FORMAT_MONO8:
    case ITKBUFFER_VAL_FORMAT_MONO10:
    case ITKBUFFER_VAL_FORMAT_MONO10PACKED:
        return false;
    default:
        return false;
    }
}

int CameraIk::getScanType()
{
    if(!(mStatus >= CS_Opened))
        return 0;
    QString scan = getValueEnumStr("DeviceScanType");
    if(scan == "AreaScan"){
        return 0;
    } else {
        return 1;
    }
}

bool CameraIk::isLineScan(int scanType)
{
    return scanType == 1;
}

CameraTriggerType CameraIk::getFrameTriggerMode(const QString &camName)
{
    if(camName != mCamConfig.name)
        return CTT_Off;
    if(!(mStatus >= CS_Opened))
        return CTT_Off;
    setValueEnumByStr("TriggerSelector", "FrameStart");
    int triggerMode = getValueEnum("TriggerMode");
    if(triggerMode == 0){
        return CTT_Off;
    }
    int triggerSource = getValueEnum("TriggerSource");
    return (triggerSource == 3) ? CTT_Software :
               CameraTriggerType(triggerSource + CTT_Line1);
}

FloatValue CameraIk::getFrameTriggerDelay(const QString &camName)
{
    if(camName != mCamConfig.name)
        return FloatValue();
    if(!(mStatus >= CS_Opened))
        return FloatValue();
    if(getFrameTriggerMode(camName) == CTT_Off){
        return FloatValue();
    }
    setValueEnumByStr("TriggerSelector", "FrameStart");
    int triggerMode = getValueEnum("TriggerMode");
    if(triggerMode == 0){
        return FloatValue();
    }
    IntValue delay = getValueInt64("TriggerDelay");
    FloatValue value;
    value.val = delay.val;
    value.max = delay.max;
    value.min = delay.min;
    return value;
}

CameraTriggerType CameraIk::getLineTriggerMode(const QString &camName)
{
    if(camName != mCamConfig.name)
        return CTT_Off;
    if(!(mStatus >= CS_Opened))
        return CTT_Off;
    setValueEnumByStr("TriggerSelector", "LineStart");
    int lineTrigMode = getValueEnum("TriggerMode");
    if(lineTrigMode == 0){
        return CTT_Off;
    }
    QString lineTriggerSource = getValueEnumStr("TriggerSource");
    int triggerSource = getValueEnum("TriggerSource");
    return (lineTriggerSource == "RotaryEncoder1") ? CTT_FrequencyConverter :
               CameraTriggerType(triggerSource + CTT_Line1);
}

IntValue CameraIk::getWidth(const QString &camName)
{
    if(camName != mCamConfig.name)
        return IntValue();
    if(!(mStatus >= CS_Opened))
        return IntValue();
    return getValueInt64("Width");
}

IntValue CameraIk::getHeight(const QString &camName)
{
    if(camName != mCamConfig.name)
        return IntValue();
    if(!(mStatus >= CS_Opened))
        return IntValue();
    return getValueInt64("Height");
}

IntValue CameraIk::getOffsetX(const QString &camName)
{
    if(camName != mCamConfig.name)
        return IntValue();
    if(!(mStatus >= CS_Opened))
        return IntValue();
    return getValueInt64("OffsetX");
}

FloatValue CameraIk::getExposureTime(const QString &camName)
{
    if(camName != mCamConfig.name)
        return FloatValue();
    if(!(mStatus >= CS_Opened))
        return FloatValue();
    return getValueDouble("ExposureTime");
}

FloatValue CameraIk::getGain(const QString &camName)
{
    if(camName != mCamConfig.name)
        return FloatValue();
    if(!(mStatus >= CS_Opened))
        return FloatValue();
    return getValueDouble("DigitalGain");
}
//分倍频
IntValue CameraIk::getMul(const QString& camName)
{
    if(camName != mCamConfig.name)
        return IntValue();
    if(!(mStatus >= CS_Opened))
        return IntValue();
    if(getLineTriggerMode(camName) == CTT_Off){
        return IntValue();
    }
    IntValue mul;
    mul.val = getValueEnumStr("RotaryEncoderMultiplier").mid(1).toInt();
    mul.inc = 1;
    mul.max = 256;
    mul.min = 1;
    return mul;
}
IntValue CameraIk::getPostDiv(const QString& camName)
{
    if(camName != mCamConfig.name)
        return IntValue();
    if(!(mStatus >= CS_Opened))
        return IntValue();
    if(getLineTriggerMode(camName) == CTT_Off){
        return IntValue();
    }
    IntValue mul = getValueInt64("RotaryEncoderDivider");
    return mul;
}

void CameraIk::triggerSoftware()
{
    setCommand("TriggerSoftware");
}
void CameraIk::setFrameTriggerMode(const QString &camName, const CameraTriggerType &mode)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    setValueEnumByStr("TriggerSelector", "FrameStart");
    if(mode == CTT_Off){
        setValueEnumByStr("TriggerMode", "Off");
    } else {
        setValueEnumByStr("TriggerMode", "On");
        setValueEnum("TriggerSource", mode - CTT_Line1);
    }
}

void CameraIk::setFrameTriggerDelay(const QString &camName, const float &delay)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    if(getFrameTriggerMode(camName) == CTT_Off)
        return;
    setValueEnumByStr("TriggerSelector", "FrameStart");
    setValueInt64("TriggerDelay", delay);
}

void CameraIk::setLineTriggerMode(const QString &camName, const CameraTriggerType& mode)
{
    if(camName != mCamConfig.name)
        return;
    if(!(mStatus == CS_Opened))
        return;
    setValueEnumByStr("TriggerSelector", "LineStart");
    if(mode == CTT_Off){
        setValueEnumByStr("TriggerMode", "Off");
    } else {
        setValueEnumByStr("TriggerMode", "On");
        if(mode == CTT_FrequencyConverter){
            setValueEnumByStr("TriggerSource", "RotaryEncoder1");
        } else {
            setValueEnum("TriggerSource", mode - CTT_Line1);
        }
    }
}

void CameraIk::setExposureTime(const QString& camName, const float &value)
{
    if(camName != mCamConfig.name)
        return;
    if(!(mStatus >= CS_Opened))
        return;
    setValueDouble("ExposureTime", value);
}

void CameraIk::setGain(const QString& camName, const float &gain)
{
    if(camName != mCamConfig.name)
        return;
    if(!(mStatus >= CS_Opened))
        return;
    setValueDouble("AnalogueGain", gain);
}

void CameraIk::setWidth(const QString& camName, const int& width)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    setValueInt64("Width", width);
}
void CameraIk::setHeight(const QString& camName, const int& height)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    setValueInt64("Height", height);
}

void CameraIk::setOffsetX(const QString &camName, const int &off_x)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    setValueInt64("OffsetX", off_x);
}
void CameraIk::setMul(const QString& camName, const int& mul)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    if(getLineTriggerMode(camName) == CTT_Off)
        return;
    setValueEnumByStr("RotaryEncoderMultiplier", QString("x%1").arg(mul).toStdString().data());
}
void CameraIk::setPostDiv(const QString& camName, const int& postDiv)
{
    if(camName != mCamConfig.name)
        return;
    if(mStatus != CS_Opened)
        return;
    if(getLineTriggerMode(camName) == CTT_Off)
        return;
    setValueInt64("RotaryEncoderDivider", postDiv);
}

int CameraIk::getPixelFormat()
{
    char pixelFormat[16];
    uint32_t pixelFormatLen = 16;
    ITKSTATUS nRet = ITKSTATUS_OK;
    nRet = ItkDevToString(m_handle, "PixelFormat", pixelFormat, &pixelFormatLen);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << " PixelFormat fail! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
        return ITKBUFFER_VAL_FORMAT_MONO8;
    }
    if (strcmp(pixelFormat, "Mono8") == 0)
        return ITKBUFFER_VAL_FORMAT_MONO8;
    else if (strcmp(pixelFormat, "Mono10") == 0)
        return ITKBUFFER_VAL_FORMAT_MONO10;
    else if (strcmp(pixelFormat, "Mono10Packed") == 0)
        return ITKBUFFER_VAL_FORMAT_MONO10PACKED;
    else if (strcmp(pixelFormat, "BayerGR8") == 0)
        return ITKBUFFER_VAL_FORMAT_BAYER_GR8;
    else if (strcmp(pixelFormat, "BayerRG8") == 0)
        return ITKBUFFER_VAL_FORMAT_BAYER_RG8;
    else if (strcmp(pixelFormat, "BayerGB8") == 0)
        return ITKBUFFER_VAL_FORMAT_BAYER_GB8;
    else if (strcmp(pixelFormat, "BayerBG8") == 0)
        return ITKBUFFER_VAL_FORMAT_BAYER_BG8;
    else
        return ITKBUFFER_VAL_FORMAT_MONO8;
}


void CameraIk::createStreamAndBuffer()
{
    ITKSTATUS nRet = ITKSTATUS_OK;
    uint32_t streamCount = 0;
    int64_t nWidth = 0;
    int64_t nHeight = 0;
    uint32_t nFormat = ITKBUFFER_VAL_FORMAT_MONO8;
    int64_t nImageSize = 0;
    nRet = ItkDevGetStreamCount(m_handle, &streamCount);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() <<" ItkDevGetStreamCount fail! ErrorCode: "<< QByteArray::number(nRet,16).toStdString();
        return;
    }

    nWidth = getValueInt64("Width").val;

    nHeight = getValueInt64("Height").val;

    nFormat = getPixelFormat();

    nRet = ItkBufferNew(nWidth, nHeight, nFormat, &m_buffer);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << " ItkBufferNew fail! ErrorCode: "<< QByteArray::number(nRet,16).toStdString();
        return;
    }
    nRet = ItkBufferGetPrm(m_buffer, ITKBUFFER_PRM_SIZE, &nImageSize);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << " ItkBufferGetPrm fail! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
        return;
    }

    m_bufferData = (unsigned char*)malloc(nImageSize);
    if (m_bufferData == NULL){
        LOG(WARNING) << mCamConfig.name.toStdString() << " malloc fail! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
        return;
    }

    nRet = ItkDevAllocStream(m_handle, 0, m_buffer, &m_hStream);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << " ItkDevAllocStream fail! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
        return;
    }
}
void CameraIk::configureStream()
{
    ITKSTATUS nRet = ITKSTATUS_OK;

    uint32_t startMode = ITKSTREAM_VAL_START_MODE_NON_BLOCK;
    nRet = ItkStreamSetPrm(m_hStream, ITKSTREAM_PRM_START_MODE, &startMode);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << " ITKSTREAM_PRM_START_MODE fail! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
        return;
    }
    uint32_t xferMode = ITKSTREAM_VAL_TRANSFER_MODE_SYNCHRONOUS_WITH_PROTECT;
    nRet = ItkStreamSetPrm(m_hStream, ITKSTREAM_PRM_TRANSFER_MODE, &xferMode);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << " ITKSTREAM_PRM_TRANSFER_MODE fail! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
        return;
    }
    uint32_t timeOut = INFINITE;
    nRet = ItkStreamSetPrm(m_hStream, ITKSTREAM_PRM_TIME_OUT, &timeOut);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << " ITKSTREAM_PRM_TIME_OUT fail! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
        return;
    }

    nRet = ItkStreamRegisterCallback(m_hStream, ITKSTREAM_VAL_EVENT_TYPE_END_OF_FRAME, imageCallBackEx, this);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << " ItkDevAllocStream fail! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
        return;
    }

    nRet = ItkDevRegisterCallback(m_handle, "DeviceRemove", removeCallback, this);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << " ItkDevAllocStream fail! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
        return;
    }
}


void CameraIk::setValueBool(const char* strKey, bool value)
{
    ITKSTATUS nRet = ITKSTATUS_OK;
    nRet = ItkDevSetBool(m_handle, strKey, value);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " set failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
}
void CameraIk::setValueEnum(const char* strKey, unsigned int value)
{
    ITKSTATUS nRet = ITKSTATUS_OK;
    char enumName[128];
    uint32_t enumNameLen = 128;
    uint32_t featureValueCount = 0;
    QList<QString> enumListStr;

    nRet = ItkDevGetEnumCount(m_handle, strKey, &featureValueCount);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " ItkDevGetEnumCount failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }

    for (uint32_t i = 0; i < featureValueCount; i++){
        nRet = ItkDevGetEnumString(m_handle, strKey, i, enumName, &enumNameLen);
        enumListStr << enumName;
        if (ITKSTATUS_OK != nRet){
            LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " ItkDevGetEnumString failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
        }
    }
    nRet = ItkDevFromString(m_handle, strKey, enumListStr.at(value).toStdString().data());
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " ItkDevFromString failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
}

void CameraIk::setValueEnumByStr(const char *strKey, const char *value)
{
    ITKSTATUS nRet = ITKSTATUS_OK;
    nRet = ItkDevFromString(m_handle, strKey, value);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " setValueEnumByStr failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
}
void CameraIk::setValueInt32(const char* strKey, int32_t value)
{
    ITKSTATUS nRet = ITKSTATUS_OK;
    nRet = ItkDevSetInt32(m_handle, strKey, value);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " set failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
}
void CameraIk::setValueInt64(const char* strKey, int64_t value)
{
    ITKSTATUS nRet = ITKSTATUS_OK;
    nRet = ItkDevSetInt64(m_handle, strKey, value);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " set failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
}
void CameraIk::setValueDouble(const char* strKey, double value)
{
    ITKSTATUS nRet = ITKSTATUS_OK;
    nRet = ItkDevSetDouble(m_handle, strKey, value);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " set failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
}
void CameraIk::setValueStr(const char* strKey, QString value)
{
    ITKSTATUS nRet = ITKSTATUS_OK;
    nRet = ItkDevFromString(m_handle, strKey, value.toStdString().data());
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " set failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
}
void CameraIk::setCommand(const char* strKey)
{
    ITKSTATUS nRet = ITKSTATUS_OK;
    nRet = ItkDevExecuteCommand(m_handle, strKey);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " set failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
}

bool CameraIk::getValueBool(const char* strKey)
{
    bool value;
    ITKSTATUS nRet = ITKSTATUS_OK;
    nRet = ItkDevGetBool(m_handle, strKey, &value);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " get failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
    return value;
}
unsigned int CameraIk::getValueEnum(const char* strKey)
{
    ITKSTATUS nRet = ITKSTATUS_OK;
    char enumName[128];
    uint32_t enumNameLen = 128;
    uint32_t featureValueCount = 0;
    QList<QString> enumListStr;

    nRet = ItkDevGetEnumCount(m_handle, strKey, &featureValueCount);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " ItkDevGetEnumCount failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }

    for (uint32_t i = 0; i < featureValueCount; i++){
        enumNameLen = 128;
        nRet = ItkDevGetEnumString(m_handle, strKey, i, enumName, &enumNameLen);
        enumListStr << enumName;
        if (ITKSTATUS_OK != nRet){
            LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " ItkDevGetEnumString failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
        }
    }
    char enumValue[128];
    enumNameLen = 128;
    nRet = ItkDevToString(m_handle, strKey, enumValue, &enumNameLen);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << " " << strKey << " ItkDevToString failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
    return enumListStr.indexOf(QString(enumValue));
}

QString CameraIk::getValueEnumStr(const char *strKey)
{
    ITKSTATUS nRet = ITKSTATUS_OK;
    char enumValue[128];
    uint32_t enumNameLen = 128;
    nRet = ItkDevToString(m_handle, strKey, enumValue, &enumNameLen);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " getValueEnumStr failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
    return QString(enumValue);
}
IntValue CameraIk::getValueInt32(const char* strKey)
{
    int32_t value, valueMin, valueMax, valueInc;
    ITKSTATUS nRet = ITKSTATUS_OK;
    nRet = ItkDevGetInt32(m_handle, strKey, &value);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " get failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
    nRet = ItkDevGetInt32Min(m_handle, strKey, &valueMin);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " get failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
    nRet = ItkDevGetInt32Max(m_handle, strKey, &valueMax);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " get failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
    nRet = ItkDevGetInt32Inc(m_handle, strKey, &valueInc);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " get failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
    IntValue iv;
    iv.val = value;
    iv.max = valueMax;
    iv.min = valueMin;
    iv.inc = valueInc;
    return iv;
}
IntValue CameraIk::getValueInt64(const char* strKey)
{
    int64_t value, valueMin, valueMax, valueInc;
    ITKSTATUS nRet = ITKSTATUS_OK;
    nRet = ItkDevGetInt64(m_handle, strKey, &value);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " get failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
    nRet = ItkDevGetInt64Min(m_handle, strKey, &valueMin);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " get failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
    nRet = ItkDevGetInt64Max(m_handle, strKey, &valueMax);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " get failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
    nRet = ItkDevGetInt64Inc(m_handle, strKey, &valueInc);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " get failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
    IntValue iv;
    iv.val = value;
    iv.max = valueMax;
    iv.min = valueMin;
    iv.inc = valueInc;
    return iv;
}
FloatValue CameraIk::getValueDouble(const char* strKey)
{
    double value, valueMin, valueMax;
    ITKSTATUS nRet = ITKSTATUS_OK;
    nRet = ItkDevGetDouble(m_handle, strKey, &value);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " get failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
    nRet = ItkDevGetDoubleMin(m_handle, strKey, &valueMin);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " get failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
    nRet = ItkDevGetDoubleMax(m_handle, strKey, &valueMax);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " get failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
    FloatValue fv;
    fv.val = value;
    fv.max = valueMax;
    fv.min = valueMin;
    return fv;
}
QString CameraIk::getValueStr(const char* strKey)
{
    char value[128];
    uint32_t length;
    ITKSTATUS nRet = ITKSTATUS_OK;
    nRet = ItkDevToString(m_handle, strKey, value, &length);
    if (ITKSTATUS_OK != nRet){
        LOG(WARNING) << mCamConfig.name.toStdString() << strKey << " get failed! ErrorCode: " << QByteArray::number(nRet,16).toStdString();
    }
    return value;
}
